﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.ComponentModel;
using Galaktika.BI.Runtime.Services;
using Galaktika.BI.Runtime;
using Galaktika.BI.Charting;
using Galaktika.BI.Charting.PivotChart;
using Galaktika.BI.Silverlight.Controls.General;
using Galaktika.BI.Silverlight.Intermediate;
using System.Collections.ObjectModel;
using Galaktika.BI.Silverlight.Controls.OLAP.Descriptions;
using Galaktika.BI.Silverlight.Controls.Data;
using Ranet.Olap.Core;
using Ranet.Olap.Core.Data;
using Galaktika.BI.Silverlight.Intermediate.Charting;
using Galaktika.BI.Extensibility.Dom;
using Ranet.AgOlap.Controls.ContextMenu;
using Galaktika.BI.Silverlight.Services;
using Galaktika.BI.Silverlight.Controls.PivotGrid;
using Galaktika.BI.Silverlight.Charting;
using Ranet.Olap.Core.Providers.ClientServer;
using Ranet.AgOlap.Controls.General;
using Ranet.AgOlap.Controls.DataSourceInfo;
using Ranet.AgOlap.Controls.Forms;
using Visifire.Charts;

namespace Galaktika.BI.Silverlight.Controls.Charting
{
    public partial class RanetChart_v2 : UserControl, IEditableObject, IBindableObject
    {
        private string m_PaletteName;
        private ObjectCollection itemNames;
        private static IAppManager service;
        private static Dictionary<string, PaletteCollection> paletteRepository;
        private Storyboard resDoubleClickTimer;
        private ChartProperties m_ChartProperties;
        private LineChartProperties m_LineChartProperties;
        private PieChartProperties m_PieChartProperties;

        private List<DataSeries> m_DesignData;
        private PivotDataLoaderEx m_PivotDataLoader;
        private DataPoint m_SelectedDataPoint;
        private ChartingCommon chartingCommon;

        public RanetChart_v2()
        {
            InitializeComponent();

            m_ChartProperties = new ChartProperties();

            m_LineChartProperties = new LineChartProperties();

            m_PieChartProperties = new PieChartProperties();

            ALineSeriesCollection = new LineSeriesPropertiesCollection();

            APieSectorCollection = new PieSectorPropertiesCollection();

            ABubbleSeriesCollection = new CustomList<BubbleSeriesProperties>();

            AActionInfo = new CustomList<ActionInfo>();

            this.chartingCommon = new ChartingCommon(this.chart2);

            this.Legend = new Legend();
            this.ALegendFont = new Font();
            this.ALegendFont.Size = 11;
            this.ACaptionFont.Size = 13;
             this.itemNames = new ObjectCollection();
            //
            // events
            //
            resDoubleClickTimer = new Storyboard();
            resDoubleClickTimer.Duration = new Duration(TimeSpan.FromMilliseconds(250.0));
            resDoubleClickTimer.Completed += resDoubleClickTimer_Completed;

            this.chart2.MouseLeftButtonDown += chart_MouseLeftButtonDown;
            this.chart2.MouseLeftButtonUp += chart_MouseLeftButtonUp;
            this.chart2.DrillDown += chart2_DrillDown;

            this.AttachContextMenu(p =>
            {
                return this.ContextMenu;
            });
        }

        void chart2_DrillDown(object sender, DrillDownEventArgs args)
        {
            if (args != null && args.DataPoint != null)
            {
                this.m_SelectedDataPoint = args.DataPoint;
                if (this.m_SelectedDataPoint != null)
                {
                    this.ContextMenu.Tag = this.m_SelectedDataPoint;
                    this.chartingCommon.ParseArgsOnMenuItems(this.ContextMenu);
                }
            }
        }
        
        private byte m_ClickCount = 0;
        MouseButtonEventArgs m_LastArgs;
        void resDoubleClickTimer_Completed(object sender, EventArgs e)
        {
            if (m_ClickCount > 1)
            {
                this.OnMouseDoubleClick(m_LastArgs);
            }
            m_ClickCount = 0;
        }

        void chart_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            m_ClickCount++;
            m_LastArgs = e;
            resDoubleClickTimer.Begin();
        }

        void chart_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            this.OnMouseClick(e);
        }       

        CustomContextMenu m_ContextMenu = null;
        public CustomContextMenu ContextMenu
        {
            get
            {
                if (m_ContextMenu == null)
                {
                    m_ContextMenu = new CustomContextMenu();
                    ReCreateContextMenu(m_ContextMenu);
                    Raise_ContextMenuCreated();
                }
                return m_ContextMenu;
            }
        }

        private void ReCreateContextMenu(CustomContextMenu contextMenu)
        {
            contextMenu.Items.Clear();

            if (this.AActionInfo != null && this.AActionInfo.Count > 0)
            {
                foreach (ActionInfo info in this.AActionInfo)
                {
                    if (info.ACaption.Contains("---"))
                    {
                        contextMenu.AddMenuSplitter();
                    }
                    else
                    {
                        var item2 = new ContextMenuItem(info.ACaption);
                        item2.ItemClick += SeriesAreaContextMenu_ItemClick;
                        item2.Tag = info;
                        item2.Icon = null;
                        contextMenu.AddMenuItem(item2);
                    }
                }
                if (contextMenu.Items.Count > 0)
                {
                    contextMenu.AddMenuSplitter();
                }
            }

            //item = new ContextMenuItem(Localization.Mnu_Customize);
            //item.Tag = this.CustomizeWindow;
            //contextMenu.AddMenuItem(item);
            //item.ItemClick += new EventHandler(CustomizeItem_ItemClick);

            var item = new ContextMenuItem(Localization.Mnu_Zooming);
            item.Tag = this.AUseZooming;
            contextMenu.AddMenuItem(item);
            item.ItemClick += new EventHandler(ZoomingItem_ItemClick);
            contextMenu.AddMenuSplitter();

            var showMDX = new ContextMenuItem(Localization.Mnu_ShowMDX);
            //item.Tag = this.AEnabledZooming;
            contextMenu.AddMenuItem(showMDX);
            showMDX.ItemClick += new EventHandler(ShowMDX_ItemClick); 

            var export = new ContextMenuItem(Localization.AppTask_ExportToExcel);
            contextMenu.AddMenuItem(export);
            export.ItemClick += new EventHandler(Export_ItemClick);
            //return contextMenu;
        }

        void Export_ItemClick(object sender, EventArgs e)
        {
            ExportToExcel();
        }

        private void ExportToExcel()
        {
            var args = new ServiceCommandArgs(ServiceCommandType.ExportToExcel);
            var dataLoaderEx = new PivotDataLoaderEx(this);
            dataLoaderEx.Context = this.Context;
            IBindingManager manager = null;
            this.Bindings.TryGetValue("ADataSource", out manager);
            dataLoaderEx.BindManager = manager;
            dataLoaderEx.PerformServiceCommand(XmlSerializationUtility.Obj2XmlStr(args, Common.Namespace), args);
        }

        void ShowMDX_ItemClick(object sender, EventArgs e)
        {
            GetDataSourceInfo();
        }

        private void ZoomingItem_ItemClick(object sender, EventArgs e)
        {
            if (((ContextMenuItem) sender).Tag is bool)
            {
                ((ContextMenuItem) sender).Tag = !(bool)((ContextMenuItem) sender).Tag;
                this.AUseZooming = (bool)((ContextMenuItem) sender).Tag;
            }
            if (this.AUseZooming)
            {
                ((ContextMenuItem) sender).Icon = UriResources.Images.ActionNode16;
                this.zoomScroll2.Visibility = Visibility.Visible;
                //TODO: Реализовать Zooming
                return;
            }
            this.zoomScroll2.Visibility = Visibility.Collapsed;
            ((ContextMenuItem) sender).Icon = null;
        }

        private void CustomizeItem_ItemClick(object sender, EventArgs e)
        {
            //TODO: Реализовать настройку.
        }


        public event EventHandler ContextMenuCreated;
        private void Raise_ContextMenuCreated()
        {
            EventHandler handler = this.ContextMenuCreated;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }


        void SeriesAreaContextMenu_ItemClick(object sender, EventArgs e)
        {
            var item = sender as ContextMenuItem;
            this.m_SelectedDataPoint = null;
            if (item != null && item.Tag != null)
            {
                if (item.Tag is ActionInfo)
                {
                    var ai = item.Tag as ActionInfo;
                    if (ai != null && ai.AActionInvoker != null &&
                        ((BrickActionInvoker)ai.AActionInvoker).Action != null)
                    {
                        var args =
                            new List<ArgumentEntry>(((BrickActionInvoker)ai.AActionInvoker).Parameters);

                        var mi = this.ContextMenu.Tag as DataPoint;
                        if (mi != null)
                        {
                            foreach (var arg in this.chartingCommon.GetContextArgs(mi, mi.Parent))
                            {
                                args.Add(new ArgumentEntry(arg.Key, arg.Value));
                            }
                        }
                        ScriptEngine.Execute(new MockCaller(this.Context),
                                             ((BrickActionInvoker)ai.AActionInvoker).Action, args);
                    }
                    return;
                }
            }
        }
       
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region Свойства для диаграммы в целом

        public Legend Legend { get; set; }

        /// <summary>
        /// Действия
        /// </summary>   
        public CustomList<ActionInfo> AActionInfo { get; set; }

        #region Свойства для заголовка диаграммы
        /// <summary>
        /// Определяет заголовок для всей диаграммы
        /// </summary>
        public string ACaption
        {
            get
            {
                return m_ChartProperties.Caption;
            }
            set
            {
                m_ChartProperties.Caption = value;
            }
        }

        /// <summary>
        /// Цвет заголовка диаграммы
        /// </summary>
        public Color ACaptionColor
        {
            get
            {
                return m_ChartProperties.CaptionColor;
            }
            set
            {
                m_ChartProperties.CaptionColor = value;
            }
        }

        /// <summary>
        /// Шрифт заголовка диаграммы
        /// </summary>
        public Font ACaptionFont
        {
            get
            {
                return m_ChartProperties.CaptionFont;
            }
            set
            {
                m_ChartProperties.CaptionFont = value;
            }
        }
        #endregion Свойства для заголовка диаграммы

        #region Свойства для настройки отображения самой диаграммы
        /// <summary>
        /// Источник данных
        /// </summary>
        public object ADataSource
        {
            get;
            set;
        }

        /// Тип диаграммы
        public ChartType AChartType
        {
            get
            {
                return m_ChartProperties.ChartType;
            }
            set
            {
                m_ChartProperties.ChartType = value;
            }
        }

        /// <summary>
        /// Цвет фона для всей диаграммы
        /// </summary>
        public Color ABackColor
        {
            get
            {
                return m_ChartProperties.BackColor;
            }
            set
            {
                m_ChartProperties.BackColor = value;
            }
        }

        /// <summary>
        /// Прозрачность
        /// </summary>
        public double AOpacity
        {
            get
            {
                return m_ChartProperties.Opacity;
            }
            set
            {
                m_ChartProperties.Opacity = value;
            }
        }

        /// <summary>
        /// Управляет необходимостью отображения значений на диаграмме
        /// </summary>
        public bool AShowValues
        {
            get
            {
                return m_ChartProperties.ShowValues;
            }
            set
            {
                m_ChartProperties.ShowValues = value;
            }
        }

        /// <summary>
        /// Задает отступ для значения на графике (положительное - за пределами графика, отрицательное - внутри графика)
        /// </summary>
        public int AValueIndent
        {
            get
            {
                return m_ChartProperties.ValueIndent;
            }
            set
            {
                m_ChartProperties.ValueIndent = value;
            }
        }

        /// <summary>
        /// Формат значений на графике. 
        /// </summary>
        public String AFormatString
        {
            get
            {
                return m_ChartProperties.FormatString;
            }
            set
            {
                m_ChartProperties.FormatString = value;
            }
        }
        #endregion Свойства для настройки отображения самой диаграммы

        #region Управление 3D
        /// <summary>
        /// Вкл/Выкл отображения 3D изображения на графике
        /// </summary>
        public bool AUse3D
        {
            get
            {
                return m_ChartProperties.Use3D;
            }
            set
            {
                m_ChartProperties.Use3D = value;
            }
        }

        /// <summary>
        /// Глубина объемности графика
        /// </summary>
        public int ADepth3D
        {
            get
            {
                return m_ChartProperties.Depth3D;
            }
            set
            {
                m_ChartProperties.Depth3D = value;
            }
        }

        #endregion Управление 3D

        /// <summary>
        /// Признак работы в режиме фильтрации
        /// </summary>
        public bool AIsFilterMode
        {
            get
            {
                return m_ChartProperties.IsFilterMode;
            }
            set
            {
                m_ChartProperties.IsFilterMode = value;
            }
        }

        /// <summary>
        /// Массив допустимых индексов серий (столбцов источника).
        /// </summary>
        public string ASeriesIndices
        {
            get
            {
                return m_ChartProperties.SeriesIndices;
            }
            set
            {
                m_ChartProperties.SeriesIndices = value;
            }
        }

        /// <summary>
        /// Массив допустимых индексов данных (строк источника).
        /// </summary>
        public string ADataIndices
        {
            get
            {
                return m_ChartProperties.DataIndices;
            }
            set
            {
                m_ChartProperties.DataIndices = value;
            }
        }

        /// <summary>
        /// Признак использования масштабирования
        /// </summary>
        public bool AUseZooming
        {
            get
            {
                return m_ChartProperties.UseZooming;
            }
            set
            {
                m_ChartProperties.UseZooming = value;
            }
        }

        #region Управление легендой
        /// <summary>
        /// Вкл/Выкл отображения легенды на диаграмме
        /// </summary>
        public bool AUseLegend
        {
            get
            {
                return m_ChartProperties.UseLegend;
            }
            set
            {
                m_ChartProperties.UseLegend = value;
            }
        }

        /// <summary>
        /// Устанавливает позицию легенды
        /// </summary>
        public Point ALegendLocation
        {
            get
            {
                return m_ChartProperties.LegendLocation;
            }
            set
            {
                m_ChartProperties.LegendLocation = value;
            }
        }

        /// <summary>
        /// Определяет привязку легенды к углу
        /// </summary>
        public LegendDockStyle ALegendDock
        {
            get
            {
                return m_ChartProperties.LegendDock;
            }
            set
            {
                m_ChartProperties.LegendDock = value;
            }
        }

        /// <summary>
        /// Шрифт для легенды
        /// </summary>
        public Font ALegendFont
        {
            get
            {
                return m_ChartProperties.LegendFont;
            }
            set
            {
                m_ChartProperties.LegendFont = value;
            }
        }

        /// <summary>
        /// True – элементы в легенде будут располагаться вертикально False - элементы в легенде будут располагаться горизонтально
        /// </summary>
        public bool AUseLegendInvert
        {
            get
            {
                return m_ChartProperties.UseLegendInvert;
            }
            set
            {
                m_ChartProperties.UseLegendInvert = value;
            }
        }
        #endregion Управление легендой

        /// <summary>
        /// Название используемой палитры
        /// </summary>
        public String APaletteName
        {
            get
            {
                return m_ChartProperties.PaletteName;
            }
            set
            {
                m_ChartProperties.PaletteName = value;
            }
        }

        /// <summary>
        /// Источник палитры (имя чарта DevExpress из этой же формы).
        /// </summary>
        public string APaletteSource
        {
            get
            {
                return m_ChartProperties.PaletteSource;
            }
            set
            {
                m_ChartProperties.PaletteSource = value;
            }
        }

        /// <summary>
        /// Цвет шрифта
        /// </summary>
        public Color AFontColor
        {
            get
            {
                return m_ChartProperties.FontColor;
            }
            set
            {
                m_ChartProperties.FontColor = value;
            }
        }
        #endregion Свойства для диаграммы в целом

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region Свойства линейных (Line) диаграмм
        /// <summary>
        /// Определяет отступы (X-слева, Y-сверху, Width-справа, Height-снизу) для графика
        /// </summary>
        public Rect APadding
        {
            get
            {
                return m_LineChartProperties.Padding;
            }
            set
            {
                m_LineChartProperties.Padding = value;
            }
        }

        #region Подписи для осей
        /// <summary>
        /// Пользовательская надпись по оси X
        /// </summary>
        public string AXCaption
        {
            get
            {
                return m_LineChartProperties.XCaption;
            }
            set
            {
                m_LineChartProperties.XCaption = value;
            }
        }

        /// <summary>
        /// Пользовательская надпись по оси Y
        /// </summary>
        public string AYCaption
        {
            get
            {
                return m_LineChartProperties.YCaption;
            }
            set
            {
                m_LineChartProperties.YCaption = value;
            }
        }

        /// <summary>
        /// Видимость подписей по оси Х
        /// </summary>
        public bool AShowXLabels
        {
            get
            {
                return m_LineChartProperties.ShowXLabels;
            }
            set
            {
                m_LineChartProperties.ShowXLabels = value;
            }
        }

        /// <summary>
        /// Видимость подписей по оси Y
        /// </summary>
        public bool AShowYLabels
        {
            get
            {
                return m_LineChartProperties.ShowYLabels;
            }
            set
            {
                m_LineChartProperties.ShowYLabels = value;
            }
        }
        #endregion Подписи для осей

        /// <summary>
        /// True - перевёрнутый график. По оси X размещается ось Y и наоборот.
        /// </summary>
        public bool AUseInvertion
        {
            get
            {
                return m_LineChartProperties.UseInvertion;
            }
            set
            {
                m_LineChartProperties.UseInvertion = value;
            }
        }

        /// <summary>
        /// Угол поворота подписей по оси Х
        /// </summary>
        public double AXValuesAngle
        {
            get
            {
                return m_LineChartProperties.XValuesAngle;
            }
            set
            {
                m_LineChartProperties.XValuesAngle = value;
            }
        }

        /// <summary>
        /// Расстояние между соседними элементами на горизонтальной шкале.
        /// </summary>
        public int AHorzScale
        {
            get
            {
                return m_LineChartProperties.HorzScale;
            }
            set
            {
                m_LineChartProperties.HorzScale = value;
            }
        }

        public LineSeriesPropertiesCollection ALineSeriesCollection { get; set; }

        /// <summary>
        /// Нужно ли генерировать серии автоматически  
        /// </summary>
        public bool AAutoGenerateSeries
        {
            get
            {
                return m_LineChartProperties.AutoGenerateSeries;
            }
            set
            {
                m_LineChartProperties.AutoGenerateSeries = value;
            }
        }
        #endregion Свойства линейных (Line) диаграмм

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region Свойства для Pie - Диаграмм

        #region Позиция и размеры
        /// <summary>
        /// Определяет X - координату центра диаграммы
        /// </summary>
        public double ALocationX
        {
            get
            {
                return m_PieChartProperties.Location_X;
            }
            set
            {
                m_PieChartProperties.Location_X = value;
            }
        }

        /// <summary>
        /// Определяет Y - координату центра диаграммы
        /// </summary>
        public double ALocationY
        {
            get
            {
                return m_PieChartProperties.Location_Y;
            }
            set
            {
                m_PieChartProperties.Location_Y = value;
            }
        }

        /// <summary>
        /// Радиус диаграммы
        /// </summary>
        public double AOuterRadius
        {
            get
            {
                return m_PieChartProperties.OuterRadius;
            }
            set
            {
                m_PieChartProperties.OuterRadius = value;
            }
        }

        /// <summary>
        /// Внутренний pадиус диаграммы
        /// </summary>
        public double AInnerRadius
        {
            get
            {
                return m_PieChartProperties.InnerRadius;
            }
            set
            {
                m_PieChartProperties.InnerRadius = value;
            }
        }

        /// <summary>
        /// Индекс отображаемой серии из реальных данных
        /// </summary>
        public int ADataSeriesIndex
        {
            get
            {
                return m_PieChartProperties.DataSeriesIndex;
            }
            set
            {
                m_PieChartProperties.DataSeriesIndex = value;
            }
        }
        #endregion Позиция и размеры

        public PieSectorPropertiesCollection APieSectorCollection { get; set; }

        /// <summary>
        /// Тип отображения значений (по кругу, либо сноски)
        /// </summary>
        public LabelLayoutType ALabelLayout
        {
            get
            {
                return m_PieChartProperties.LabelLayout;
            }
            set
            {
                m_PieChartProperties.LabelLayout = value;
            }
        }

        /// <summary>
        /// Вкл/выкл отображение линий-сносок
        /// </summary>
        public bool AShowLabelJoinLine
        {
            get
            {
                return m_PieChartProperties.ShowLabelJoinLine;
            }
            set
            {
                m_PieChartProperties.ShowLabelJoinLine = value;
            }
        }

        /// <summary>
        /// Вкл/выкл отображение цветных меток
        /// </summary>
        public bool AUseColoredLabels
        {
            get
            {
                return m_PieChartProperties.UseColoredLabels;
            }
            set
            {
                m_PieChartProperties.UseColoredLabels = value;
            }
        }
        #endregion Свойства для Pie - Диаграмм

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region Свойства для Bubble - диаграмм

        /// <summary>
        /// Коллекция серий 
        /// </summary>
        public CustomList<BubbleSeriesProperties> ABubbleSeriesCollection { get; set; }

        #endregion Свойства для Bubble - диаграмм
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


        public event MouseButtonEventHandler MouseDoubleClick;
        protected void OnMouseDoubleClick(MouseButtonEventArgs e)
        {
            if (this.MouseDoubleClick != null)
            {
                this.MouseDoubleClick(this, e);
            }
        }

        public event MouseButtonEventHandler MouseClick;
        protected void OnMouseClick(MouseButtonEventArgs e)
        {
            if (this.MouseClick != null)
            {
                this.MouseClick(this, e);
            }
        }

        private void AddToChartSeriesAddedFromDesign()
        {
            this.chart2.Series.Clear();
            var filteredData = new List<DataSeries>();
            if (!String.IsNullOrEmpty(this.ADataIndices))
            {
                string points = this.GetSelectedPoints();
                foreach (string str in points.Split(new string[] { "," }, StringSplitOptions.None))
                {
                    int index = Convert.ToInt32(str);
                    if (index < m_DesignData.Count)
                    {
                        if (!filteredData.Contains(m_DesignData[index]))
                            filteredData.Add(m_DesignData[index]);
                    }
                }
            }
            else
                filteredData = m_DesignData;
            if (this.AChartType == ChartType.Bubble)
            {
                var bubbleSeries = this.chartingCommon.CreateBubbleSeries(this.ADataSource,this.AFormatString);
                foreach (var series in bubbleSeries)
                {
                    series.RenderAs = RenderAs.Bubble;
                    this.chart2.Series.Add(series);
                }
            }
            else
            {
                for (int index = 0; index < filteredData.Count; index++)
                {
                    DataSeries[] seriesArrayFromDataSource = this.chartingCommon.GetSeriesFromDataSourceFlat(this.ADataSource,this.AChartType,this.AFormatString,this.AShowValues);
                    if (this.IndexInArrayRange(this.ADataSeriesIndex, seriesArrayFromDataSource))
                    {
                        var series = seriesArrayFromDataSource[this.ADataSeriesIndex];
                        if (this.IndexInArrayRange(this.ADataSeriesIndex, seriesArrayFromDataSource) && series != null)
                        {
                            if (RanetSeriesFactory.IsSeriesWithAxes(this.AChartType))
                            {
                                series.RenderAs = RanetSeriesFactory.GetSeriesType(this.AChartType);
                                series = ApplyToSeriesViewSettingsFromDesign(series);
                                this.chart2.Series.Add(series);
                            }
                            else
                            {
                                series.RenderAs = RanetSeriesFactory.GetSeriesType(this.AChartType);
                                series = ApplyToSeriesViewSettingsFromDesign(series);
                                if (!(this.chart2.Series.Count > 0))
                                    this.chart2.Series.Add(series);
                             }
                        }
                    }
                }
            }
        }

        private DataSeries ApplyToSeriesViewSettingsFromDesign(DataSeries series)
        {
            return series;
        }

        // Входит ли индекс index в границы массива array
        private bool IndexInArrayRange(int index, DataSeries[] array)
        {
            if ((index >= 0) && (index < array.Length))
            {
                return true;
            }
            return false;
        }

        private void AddToChartSeriesAutogenerateFromDataSource(DataSeries[] seriesArrayFromDataSource)
        {
            this.chart2.Series.Clear();
            if (this.AChartType == ChartType.Bubble)
            {
                var bubbleSeries = this.chartingCommon.CreateBubbleSeries(this.ADataSource,this.AFormatString);
                foreach (var series in bubbleSeries)
                {
                    series.RenderAs = RenderAs.Bubble;
                    this.chart2.Series.Add(series);
                }
            }
            else
            {
                for (int index = 0; index < seriesArrayFromDataSource.Length; index++)
                {
                    var series = seriesArrayFromDataSource[index];
                    series.RenderAs = RanetSeriesFactory.GetSeriesType(this.AChartType);
                    this.chart2.Series.Add(series);
               }
            }
         }        

        public void UpdateChartPalettes()
        {
            //var chartingCommon = new ChartingCommon(this.chart2);
            chartingCommon.UpdateChartPalettes(this.APaletteName,this.Context);
        }
     
        /// <summary>
        /// Обновляет содержимое Chart
        /// </summary>
        public void RefreshChart()
        {
            var taskMgr = (IUserTaskManager)this.Context.Services.GetService(typeof(IUserTaskManager));
            var exe = (IExecutionContext)this.Context.Services.GetService(typeof(IExecutionContext));
            if (exe != null && taskMgr != null)
            {
                taskMgr.RunTaskAsync(
                    string.Format(Localization.AppTask_ProcessingProperties, base.Name),
                    state =>
                    {
                        string text = exe.Parse(this.Context, this.ACaption);
                        taskMgr.Dispatcher.BeginInvoke(() =>
                        {
                            this.UpdateChartPalettes();
                            this.chart2.Titles.Clear();

                            if (AAutoGenerateSeries)
                                AddToChartSeriesAutogenerateFromDataSource(m_DesignData.ToArray());
                            else
                                AddToChartSeriesAddedFromDesign();
                            var chartTitle2 = new Title();
                            chartTitle2.Text = text;
                            if (!String.IsNullOrEmpty(this.ACaptionFont.FamilyName))
                            {
                                chartTitle2.FontFamily = new FontFamily(this.ACaptionFont.FamilyName);
                                chartTitle2.FontSize = this.ACaptionFont.Size;
                                if (this.ACaptionFont.Italic)
                                {
                                    chartTitle2.FontStyle = FontStyles.Italic;
                                }
                                if (this.ACaptionFont.Bold)
                                {
                                    chartTitle2.FontWeight = FontWeights.Bold;
                                }
                            }
                            chartTitle2.Foreground =
                                new SolidColorBrush(this.ACaptionColor);
                            this.chart2.Titles.Add(chartTitle2);
                            this.chart2.Opacity = this.AOpacity;

                            // свойства внешнего вида для области графика

                            this.chart2.Background =
                                new SolidColorBrush(this.ABackColor);
                            ////Свойства диаграммы
                            if (this.AUseZooming)
                            {

                                //TODO: Реализовать масштабирование графика
                            }
                           
                            foreach (var s in this.chart2.Series)
                            {
                                s.SelectionEnabled = true;
                                s.LabelEnabled = this.AShowValues;
                                if (s.RenderAs == RenderAs.Pie)
                                    s.StartAngle = 270;
                                if (RanetSeriesFactory.IsSeriesWithAxes(this.AChartType))
                                {
                                    s.StartAngle = this.AXValuesAngle;
                                }
                            }

                            this.chart2.View3D = this.AUse3D;
                            if (RanetSeriesFactory.IsSeriesWithAxes(this.AChartType))
                            {                                
                                this.chart2.AxesY[0].Title = this.AYCaption;
                                this.chart2.AxesX[0].Title = this.AXCaption;
                                this.chart2.AxesX[0].AxisLabels.Enabled = this.AShowXLabels;
                                this.chart2.AxesY[0].AxisLabels.Enabled = this.AShowYLabels;
                            }
                       
                            string n = string.Empty;
                         
                            // Легенда

                            foreach (var l in this.chart2.Legends)
                            {
                                

                                if (this.ALegendDock == LegendDockStyle.BottomLeft)
                                {
                                    l.VerticalAlignment = VerticalAlignment.Bottom;
                                    l.HorizontalAlignment = HorizontalAlignment.Left;
                                }
                                if (this.ALegendDock == LegendDockStyle.TopLeft)
                                {
                                    l.VerticalAlignment = VerticalAlignment.Top;
                                    l.HorizontalAlignment = HorizontalAlignment.Left;
                                }
                                if (this.ALegendDock == LegendDockStyle.BottomRight)
                                {
                                    l.VerticalAlignment = VerticalAlignment.Bottom;
                                    l.HorizontalAlignment = HorizontalAlignment.Right;
                                }
                                if (this.ALegendDock == LegendDockStyle.TopRight)
                                {
                                    l.VerticalAlignment = VerticalAlignment.Top;
                                    l.HorizontalAlignment = HorizontalAlignment.Right;
                                }

                                if (!String.IsNullOrEmpty(this.ALegendFont.FamilyName))
                                {
                                    l.FontFamily = new FontFamily(this.ALegendFont.FamilyName);
                                    l.FontSize = this.ALegendFont.Size;
                                    if (this.ALegendFont.Italic)
                                        l.FontStyle = FontStyles.Italic;
                                    if (this.ALegendFont.Bold)
                                        l.FontWeight = FontWeights.Bold;
                                }
                                l.Enabled = this.AUseLegend;
                            }
                         });
                    });
            }
            ReCreateContextMenu(this.ContextMenu);
        }

        private bool UseZooming
        {
            get
            {
                //Масштабирование пока не доступно для круговой диаграммы!
                if (AChartType != ChartType.Pie && AUseZooming)
                    return true;
                else return false;
            }
        }
 
        void GetDataSourceInfo()
        {
            ServiceCommandArgs args = new ServiceCommandArgs(ServiceCommandType.GetDataSourceInfo, null);
            m_PivotDataLoader.PerformServiceCommand(XmlSerializationUtility.Obj2XmlStr(args, Common.Namespace), args);
        }

        void Loader_DataLoaded(object sender, DataLoaderEventArgs e)
        {
            try
            {
                if (e.Error != null)
                {
                    return;
                }

                if (e.Result.ContentType == InvokeContentType.Error)
                {
                    return;
                }

                var serviceArgs = e.UserState as ServiceCommandArgs;
                if (serviceArgs != null)
                {
                    ServiceCommandType actionType = serviceArgs.Command;
                    if (actionType == ServiceCommandType.GetDataSourceInfo)
                    {
                        if (!string.IsNullOrEmpty(e.Result.Content))
                        {
                            var info = XmlSerializationUtility.XmlStr2Obj<DataSourceInfoArgs>(e.Result.Content);
                            ShowDataSourceInfo(info);
                        }
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        void ShowDataSourceInfo(DataSourceInfoArgs args)
        {
            if (args != null)
            {
                var dlg = new ModalDialog();
                //dlg.Caption = Localization.DataSourceInfoDialog_Caption;
                dlg.MinHeight = 300;
                dlg.MinWidth = 400;
                dlg.Height = 400;
                dlg.Width = 500;

                var dsInfo = new DataSourceInfoControl();
                dlg.Content = dsInfo;
                dsInfo.Initialize(args);

                dlg.Show();
            }
        }


        #region IEditableObject Members

        public void BeginEdit()
        {

        }

        public void CancelEdit()
        {

        }
  
        public void EndEdit()
        {
            IBindingManager manager = null;
            this.Bindings.TryGetValue("ADataSource", out manager);
            m_DesignData = new List<DataSeries>();
            m_PivotDataLoader = new PivotDataLoaderEx(this) { Context = this.Context, BindManager = manager };
            m_PivotDataLoader.DataLoaded += Loader_DataLoaded;
            m_DesignData = chartingCommon.ProcessPivotTable(this.ADataSource,this.AChartType, this.AFormatString,this.AUseLegend);//this.ProcessPivotTable();
            RefreshChart();
        }

        #endregion

        #region IBindableObject Members

        public IBindingContext Context { get; set; }

        private IDictionary<string, IBindingManager> m_Bindings;
        public IDictionary<string, IBindingManager> Bindings
        {
            get
            {
                if (m_Bindings == null)
                {
                    m_Bindings = new SafeDictionary<string, IBindingManager>();
                }

                return m_Bindings;
            }
        }

        #endregion

        #region Методы для работы с реальными данными       

        // Возвращает массив выделенных строки в Pivot table в виде строки
        private string GetSelectedPoints()
        {
            // ограничение аргументов - это выделенные строки
            int[] selectedPointsIndexes = this.GetSelectedArguments();

            // если еще есть ограничение аргументов через введенное пользователем в свойстве APointsFilter
            // тогда получаю общие индексы из selectedPointsIndexes и filterPointsIndexes (пересечение)
            if (!string.IsNullOrEmpty(this.ADataIndices))
            {
                int[] filterPointsIndexes = this.ParseFilter(this.ADataIndices);
                selectedPointsIndexes = filterPointsIndexes;
                    //this.GetIntersectionOfArrays(selectedPointsIndexes, filterPointsIndexes);
            }

            string selectedRows = string.Empty;
            foreach (int row in selectedPointsIndexes)
            {
                if (!string.IsNullOrEmpty(selectedRows))
                {
                    selectedRows += ",";
                }
                selectedRows += row.ToString();
            }
            return selectedRows;
        }

        // Возвращает массив выделенных строки в Pivot table
        private int[] GetSelectedArguments()
        {
            object selectedRows = null;//this.Context.UserData[Utils.MULTI_SELECT_DATA_INDICIES];
            if (selectedRows != null)
            {
                return (int[])selectedRows;
            }
            return new int[] { };
        }

        // Разбивает строку на элементы, представляющие собой целые числа - индексы
        private int[] ParseFilter(string stringFilter)
        {
            List<int> indexesInFilterResult = new List<int>();

            List<string> filterParts = new List<string>(stringFilter.Trim().Split(','));
            foreach (string filterPart in filterParts)
            {
                indexesInFilterResult.AddRange(this.ParsePartFilter(filterPart));
            }

            return indexesInFilterResult.ToArray();
        }

        // Возвращает диапазон индексов из части фильтра
        private int[] ParsePartFilter(string stringPartFilter)
        {
            List<int> indexesInFilterResult = new List<int>();
            List<string> indexesRange = new List<string>(stringPartFilter.Trim().Split('-'));
            if (indexesRange.Count > 0)
            {
                int indexMin = this.GetMinIndex(indexesRange);
                int indexMax = this.GetMaxIndex(indexesRange);
                for (int indexValue = indexMin; indexValue <= indexMax; indexValue++)
                {
                    indexesInFilterResult.Add(indexValue);
                }
            }
            return indexesInFilterResult.ToArray();
        }

        // Возвращает минимальное целое значение из списка строк indexesRange
        private int GetMinIndex(List<string> indexesRange)
        {
            int indexMinResult = int.MaxValue;
            foreach (string indexString in indexesRange)
            {
                int indexValue = 0;
                if (int.TryParse(indexString, out indexValue))
                {
                    if (indexValue < indexMinResult)
                    {
                        indexMinResult = indexValue;
                    }
                }
            }

            return indexMinResult;
        }

        // Возвращает максимальное целое значение из списка строк indexesRange
        private int GetMaxIndex(List<string> indexesRange)
        {
            int indexMaxResult = int.MinValue;
            foreach (string indexString in indexesRange)
            {
                int indexValue = 0;
                if (int.TryParse(indexString, out indexValue))
                {
                    if (indexValue > indexMaxResult)
                    {
                        indexMaxResult = indexValue;
                    }
                }
            }

            return indexMaxResult;
        }
 
        /// <summary>
        /// Возвращает текущую позицию IBindingManager
        /// </summary>
        /// <returns></returns>
        private int[] GetCurrentPosition()
        {
            IBindingManager manager = this.Bindings["ADataSource"];
            if (manager != null)
            {
                //manager.Count
                return manager.Position;
            }
            return new int[] { 0 };
        }
        #endregion Методы для работы с реальными данными

        private void zoomScroll_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {

        }
    }
}

